const { app, BrowserWindow, ipcMain, screen, globalShortcut } = require('electron');
const { spawn, execSync } = require('child_process');
const ffi = require('ffi-napi');
const ref = require('ref-napi');
const path = require("path");
const os = require('os');
const WebSocket = require('ws');
// 尝试获取单实例锁
const gotTheLock = app.requestSingleInstanceLock();
if (!gotTheLock) {
  // 如果没有获取到锁，说明已经有一个实例在运行，直接退出当前实例
  app.quit();
} else {
  const port = 7133;//自定义端口
  const localIP = getLocalIP();
  // 创建一个 WebSocket 服务器，监听本地 IP 和指定端口
  const wss = new WebSocket.Server({ host: localIP, port: port });
  let mainWindow;
  let targetWindowHandle = null;
  let childProcess = null;
  // 添加全局变量存储初始窗口尺寸
  let initialWindowSize = {
    width: 800,  // 默认值
    height: 600  // 默认值
  };

  const user32 = ffi.Library('user32', {
    'FindWindowW': ['long', ['pointer', 'pointer']],
    'EnumWindows': ['bool', ['pointer', 'pointer']],
    'GetWindowTextW': ['long', ['long', 'pointer', 'long']],
    'IsWindowVisible': ['bool', ['long']],
    'SetParent': ['long', ['long', 'long']],
    'ShowWindow': ['bool', ['long', 'int']],
    'MoveWindow': ['bool', ['long', 'int', 'int', 'int', 'int', 'bool']],
    'GetWindowLongPtrW': ['long', ['long', 'int']], // 正确定义 GetWindowLongPtrW
    'SetWindowLongPtrW': ['long', ['long', 'int', 'long']],
    'SetWindowPos': ['bool', ['long', 'long', 'int', 'int', 'int', 'int', 'uint32']],
    'SetForegroundWindow': ['bool', ['long']],
    'GetForegroundWindow': ['long', []],
    'GetActiveWindow': ['long', []],
    'SetActiveWindow': ['long', ['long']],
  });

  function createWindow() {
    const { width, height } = screen.getPrimaryDisplay().workAreaSize
    mainWindow = new BrowserWindow({
      width: Math.ceil(width * 1),
      height: Math.ceil(height * 1),
      icon: path.join(__dirname, 'logo.png'),
      autoHideMenuBar: true,
      webPreferences: {
        nodeIntegration: true,
        contextIsolation: false
      }
    });
    mainWindow.maximize();
    const indexPath = path.join(__dirname, "dist/index.html")
    // mainWindow.loadFile(indexPath);
    mainWindow.loadURL('http://localhost:5173');
    mainWindow.webContents.openDevTools({ mode: 'detach' }) //打开控制台

    // 监听来自渲染进程的启动 exe 程序消息
    ipcMain.on('start-exe', (e, width, height) => {
      // 保存初始窗口尺寸
      initialWindowSize = { width, height };

      // 运行外部 exe 程序，替换为实际的程序路径
      let exePath;
      if (app.isPackaged) {
        // 打包后的路径
        exePath = path.join(process.resourcesPath, 'electron/exe/Windows', 'VirtualSim.exe');
      } else {
        // 开发环境路径
        exePath = path.join(__dirname, 'exe/Windows', 'VirtualSim.exe');
      }
      // const child = spawn(exePath);
      childProcess = spawn(exePath);

      childProcess.on('error', (error) => {
        mainWindow.webContents.send('exe-start-failed', error.message);
      });

      mainWindow.webContents.send('exe-started');
      // 等待一段时间后尝试获取并嵌入窗口
      setTimeout(() => {
        findAndEmbedWindow(width, height);
      }, 5000);
    });
    // 监听来自渲染进程的关闭 exe 程序消息
    ipcMain.on('close-exe', () => {
      try {
        // 1. 先恢复窗口原始状态
        if (targetWindowHandle) {
          // 恢复窗口样式
          const GWL_STYLE = -16;
          const WS_BORDER = 0x00800000;
          const WS_CAPTION = 0x00C00000;
          const style = user32.GetWindowLongPtrW(targetWindowHandle, GWL_STYLE);
          const newStyle = style | WS_BORDER | WS_CAPTION;
          user32.SetWindowLongPtrW(targetWindowHandle, GWL_STYLE, newStyle);

          // 移除父窗口关系
          user32.SetParent(targetWindowHandle, 0);
          // 显示窗口
          user32.ShowWindow(targetWindowHandle, 0); // 0 表示隐藏窗口
          targetWindowHandle = null;
        }

        // 2. 强制结束进程
        if (childProcess) {
          // Windows 下使用 taskkill 强制结束进程及其子进程
          try {
            execSync(`taskkill /F /T /PID ${childProcess.pid}`);
          } catch (error) {
            console.error('强制结束进程失败:', error);
          }
          childProcess = null;
        }

        // 3. 关闭 WebSocket 连接
        wss.clients.forEach(client => {
          if (client.readyState === WebSocket.OPEN) {
            client.close();
          }
        });

        mainWindow.webContents.send('exe-closed', '程序已关闭');
      } catch (error) {
        console.error('关闭程序时出错:', error);
        mainWindow.webContents.send('exe-close-failed', error.message);
      }
    });

    // 修改 IPC 事件监听器
    ipcMain.on('toggle-fullscreen', (event, { isFullscreen, handle }) => {
      try {
        // 定义常量
        const GWL_STYLE = -16;
        const WS_BORDER = 0x00800000;
        const WS_CAPTION = 0x00C00000;
        const HWND_TOP = -1;
        const SWP_SHOWWINDOW = 0x0040;
        const SWP_FRAMECHANGED = 0x0020;
        const WS_POPUP = 0x80000000;
        const WS_VISIBLE = 0x10000000;

        if (targetWindowHandle) {
          if (isFullscreen) {
            // 保存原始样式
            const originalStyle = user32.GetWindowLongPtrW(targetWindowHandle, GWL_STYLE);
            global.originalStyle = originalStyle;

            // 1. 移除父窗口关系
            user32.SetParent(targetWindowHandle, 0);

            // 2. 获取主显示器完整尺寸（包括任务栏）
            const { width, height } = screen.getPrimaryDisplay().bounds;

            // 3. 设置为全屏窗口样式
            const newStyle = WS_POPUP | WS_VISIBLE; // 使用完全重写的样式而不是修改原样式
            user32.SetWindowLongPtrW(targetWindowHandle, GWL_STYLE, newStyle);

            // 4. 设置窗口位置和大小（使用完整屏幕尺寸）
            user32.SetWindowPos(
              targetWindowHandle,
              HWND_TOP,  // 置顶
              0,         // x 坐标
              0,         // y 坐标
              width,     // 全屏宽度
              height,    // 全屏高度
              SWP_SHOWWINDOW | SWP_FRAMECHANGED // 添加 SWP_FRAMECHANGED 标志强制重绘窗口框架
            );

            // 5. 强制显示窗口
            user32.ShowWindow(targetWindowHandle, 3); // SW_MAXIMIZE = 3
          } else {
            // 还原窗口
            if (global.originalStyle) {
              user32.SetWindowLongPtrW(targetWindowHandle, GWL_STYLE, global.originalStyle);
              delete global.originalStyle;
            }

            const electronWindowHandle = mainWindow.getNativeWindowHandle().readUInt32LE(0);
            user32.SetParent(targetWindowHandle, electronWindowHandle);

            const { width, height } = mainWindow.getBounds();
            const x = (width - initialWindowSize.width) / 2;
            const y = (height - initialWindowSize.height) / 2;

            // 使用保存的初始尺寸
            user32.MoveWindow(
              targetWindowHandle,
              x,
              y,
              initialWindowSize.width,
              initialWindowSize.height,
              true
            );

            // 强制重绘窗口时也使用初始尺寸
            user32.SetWindowPos(
              targetWindowHandle,
              0,
              x,
              y,
              initialWindowSize.width,
              initialWindowSize.height,
              SWP_FRAMECHANGED
            );
          }

          // 发送状态更新到渲染进程
          mainWindow.webContents.send('fullscreen-toggled', isFullscreen);
        } else {
          throw new Error('找不到目标窗口句柄');
        }
      } catch (error) {
        console.error('切换全屏失败:', error);
        mainWindow.webContents.send('fullscreen-toggle-failed', error.message);
      }
    });

    // 所有窗口事件监听设置完成后，再注册全局快捷键
    globalShortcut.register('F11', () => {
      if (targetWindowHandle) {
        mainWindow.webContents.send('f11-pressed');
      }
    });

    globalShortcut.register('Escape', () => {
      if (targetWindowHandle) {
        mainWindow.webContents.send('escape-pressed');
      }
    });
    mainWindow.webContents.on('before-input-event', (event, input) => {
      if (input.key === 'Tab' && targetWindowHandle) {
        // 阻止 Electron 默认的 Tab 键行为
        event.preventDefault();

        // 确保目标窗口处于活动状态
        user32.SetForegroundWindow(targetWindowHandle);
        user32.SetActiveWindow(targetWindowHandle);
      }
    });
  }

  function findAndEmbedWindow(width, height) {
    // 窗口标题或模糊匹配关键字，根据实际情况修改
    const windowTitle = 'VirtualSim';
    const maxAttempts = 20;
    const interval = 1000;
    let attempts = 0;

    function tryFindWindow(width, height) {
      const wideString = ref.allocCString(windowTitle, 'ucs2');
      targetWindowHandle = user32.FindWindowW(null, wideString);

      if (targetWindowHandle) {
        console.log('找到窗口，句柄为EEEE:', targetWindowHandle);
        embedWindow(targetWindowHandle, user32, width, height);
      } else {
        // 尝试模糊匹配
        const allWindows = [];
        const EnumWindowsProc = ffi.Callback('bool', ['long', 'pointer'], (hwnd, lParam) => {
          const titleBuffer = Buffer.alloc(256);
          user32.GetWindowTextW(hwnd, titleBuffer, titleBuffer.length);
          const title = titleBuffer.toString('ucs2').replace(/\0/g, '');

          if (title.includes(windowTitle)) {
            allWindows.push({ hwnd, title });
          }
          return true;
        });

        user32.EnumWindows(EnumWindowsProc, null);

        if (allWindows.length > 0) {
          targetWindowHandle = allWindows[0].hwnd;
          embedWindow(targetWindowHandle, user32, width, height);
        } else if (attempts < maxAttempts) {
          attempts++;
          setTimeout(tryFindWindow, interval);
        } else {
          mainWindow.webContents.send('exe-embed-failed', '未能找到窗口');
        }
      }
    }

    tryFindWindow(width, height);
  }

  function embedWindow(targetWindowHandle, user32, width, height) {
    try {
      const electronWindowHandle = mainWindow.getNativeWindowHandle().readUInt32LE(0);

      // 定义常量
      const GWL_STYLE = -16;
      const GWL_EXSTYLE = -20;
      const WS_CHILD = 0x40000000;
      const WS_EX_NOACTIVATE = 0x08000000;
      const WS_EX_TRANSPARENT = 0x00000020;

      // 设置父窗口关系
      user32.SetParent(targetWindowHandle, electronWindowHandle);

      // 修改窗口基本样式为子窗口
      const style = user32.GetWindowLongPtrW(targetWindowHandle, GWL_STYLE);
      const exStyle = user32.GetWindowLongPtrW(targetWindowHandle, GWL_EXSTYLE);

      // 设置扩展样式，允许窗口接收输入
      user32.SetWindowLongPtrW(
        targetWindowHandle,
        GWL_EXSTYLE,
        exStyle & ~WS_EX_NOACTIVATE & ~WS_EX_TRANSPARENT
      );

      // 设置基本样式
      user32.SetWindowLongPtrW(
        targetWindowHandle,
        GWL_STYLE,
        (style & ~WS_CHILD) | WS_CHILD
      );

      // 调整窗口位置
      const { width: parentWidth, height: parentHeight } = mainWindow.getBounds();
      const x = (parentWidth - width) / 2;
      const y = (parentHeight - height) / 2;
      user32.MoveWindow(targetWindowHandle, x, y, width, height, true);

      // 显示窗口并设置焦点
      user32.ShowWindow(targetWindowHandle, 1);
      user32.SetForegroundWindow(targetWindowHandle);
      user32.SetActiveWindow(targetWindowHandle);

      // 发送嵌入成功消息
      const localIP = getLocalIP();
      mainWindow.webContents.send('exe-embedded', {
        ip: localIP,
        handle: targetWindowHandle
      });
    } catch (error) {
      console.error('嵌入窗口失败:', error);
      mainWindow.webContents.send('exe-embed-failed', error.message);
    }
  }

  //获取ip地址
  function getLocalIP() {
    const interfaces = os.networkInterfaces();
    for (const name of Object.keys(interfaces)) {
      for (const iface of interfaces[name]) {
        if (iface.family === 'IPv4' && !iface.internal) {
          return iface.address;
        }
      }
    }
    return '127.0.0.1';
  }

  // 处理 WebSocket 连接
  wss.on('connection', (ws) => {
    // 监听 WebSocket 消息
    ws.on('message', (message) => {
      try {
        const messageString = message.toString();
        
        const data = JSON.parse(messageString);
        
        // 将消息发送到渲染进程
        if (mainWindow) {
          mainWindow.webContents.send('ws-message', data);
        }
      } catch (error) {
        console.error('消息处理错误:', error);
      }
    });
  });

  // 监听来自渲染进程的 WebSocket 消息
  ipcMain.on('send-ws-message', (event, message) => {
    // 将消息转换为JSON字符串
    const messageString = JSON.stringify(message);
    // 向所有连接的客户端广播消息
    wss.clients.forEach((client) => {
      if (client.readyState === WebSocket.OPEN) {
        client.send(messageString);
      }
    });
  });

  ipcMain.on('focus-exe-window', (event, handle) => {
    if (handle) {
      user32.SetForegroundWindow(handle);
      user32.SetActiveWindow(handle);
    }
  });
  app.whenReady().then(() => {
    createWindow();

    app.on('activate', function () {
      if (BrowserWindow.getAllWindows().length === 0) createWindow();
    });
  });

  app.on('window-all-closed', function () {
    try {
      // 清理 exe 进程
      if (childProcess) {
        try {
          execSync(`taskkill /F /T /PID ${childProcess.pid}`);
        } catch (error) {
          console.error('强制结束进程失败:', error);
        }
        childProcess = null;
      }

      // 清理 WebSocket 连接
      if (wss) {
        wss.clients.forEach(client => {
          if (client.readyState === WebSocket.OPEN) {
            client.close();
          }
        });
        wss.close();
      }

      if (process.platform !== 'darwin') {
        app.quit();
      }
    } catch (error) {
      console.error('清理资源时出错:', error);
    }
  });

  // 在应用退出前注销所有快捷键
  app.on('will-quit', () => {
    globalShortcut.unregisterAll();
  });
}